/* eslint-disable no-console */
import { basename, join } from 'node:path';
import { mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises';
import { app, nativeImage } from 'electron';
import { formatDateTime } from '../utils/date';
import { hash } from '../utils/hash';
import { existsAsync } from '../utils/fs';
import { scriptManager } from './script-manager';
import { normalizePath } from './utils';

// 缓存文件路径
const getCachePath = () => {
  const userDataPath = app.getPath('userData');
  console.log('apps cache path:', userDataPath)
  return join(userDataPath, 'installed-apps-cache.json');
};

// 图标缓存目录
const getIconsDir = () => {
  const userDataPath = app.getPath('userData');
  return join(userDataPath, 'app-icons');
};

// 在目录中查找 exe 文件
async function findExeFilesInDirectory (dirPath: string): Promise<string[]> {
  const exeFiles: string[] = [];
  
  if (!(await existsAsync(dirPath))) {
    return exeFiles;
  }

  try {
    const entries = await readdir(dirPath);
    
    for (const entry of entries) {
      const fullPath = join(dirPath, entry);
      
      try {
        const stats = await stat(fullPath);
        
        if (stats.isFile() && entry.toLowerCase().endsWith('.exe')) {
          exeFiles.push(fullPath);
        } else if (stats.isDirectory()) {
          // 递归查找子目录（限制深度，避免太深）
          const subExeFiles = await findExeFilesInDirectory(fullPath);
          exeFiles.push(...subExeFiles);
          // 限制最多查找 10 个 exe 文件，避免性能问题
          if (exeFiles.length >= 10) {
            break;
          }
        }
      } catch {
        // 忽略无法访问的文件/目录
        continue;
      }
    }
  } catch (error) {
    console.error(`find exe files in directory ${dirPath} error:`, error);
  }
  
  return exeFiles;
}

// 从 exe 文件提取图标并保存到本地
async function extractAndSaveIcon (
  iconPath: string,
  appName: string,
  fallbackPaths: string[] = [],
): Promise<string | null> {
  const candidatePaths = [
    iconPath,
    ...fallbackPaths,
  ]
    .filter((p): p is string => Boolean(p && p.trim()))
    .map(normalizePath);

  if (candidatePaths.length === 0) {
    return null;
  }

  const uniqueCandidates = Array.from(new Set(candidatePaths));

  try {
    const iconsDir = getIconsDir();
    if (!(await existsAsync(iconsDir))) {
      await mkdir(iconsDir, { recursive: true });
    }

    const iconFileName = `${hash(appName)}.png`;
    const iconFilePath = join(iconsDir, iconFileName);
    const fileUrl = `file:///${iconFilePath.replace(/\\/g, '/')}`;

    if (await existsAsync(iconFilePath)) {
      return fileUrl;
    }

    for (const candidate of uniqueCandidates) {
      if (!(await existsAsync(candidate))) {
        console.error(`icon file not exists: ${candidate} (app: ${appName})`);
        continue;
      }

      try {
        const iconExtracted = await scriptManager.extractIconWithPowerShell(
          candidate,
          iconFilePath,
        );
        if (iconExtracted) {
          return fileUrl;
        }
      } catch (error) {
        console.error(
          `PowerShell extract icon failed: ${candidate}`,
          error,
        );
      }

      const image = nativeImage.createFromPath(candidate);
      if (!image.isEmpty()) {
        const pngBuffer = image.toPNG();
        await writeFile(iconFilePath, pngBuffer as any);
        return fileUrl;
      }

      console.error(`cannot extract icon from file: ${candidate} (app: ${appName})`);
    }

    return null;
  } catch (error) {
    console.error('extract and save icon failed:', appName, error);
    return null;
  }
}

// 从缓存读取
async function getAppsFromCache (): Promise<InstalledApp[] | null> {
  try {
    const cachePath = getCachePath();
    if (await existsAsync(cachePath)) {
      const data = await readFile(cachePath, 'utf-8');
      const cache = JSON.parse(data);
      // 检查缓存是否过期（24小时）
      const now = Date.now();
      if (now - cache.timestamp < 24 * 60 * 60 * 1000) {
        return cache.apps;
      }
    }
  } catch (error) {
    console.error('read cache file error:', error);
  }
  return null;
}

// 保存到缓存
async function saveAppsToCache (apps: InstalledApp[]): Promise<void> {
  try {
    const cachePath = getCachePath();
    const cacheDir = cachePath.slice(0, Math.max(0, cachePath.lastIndexOf('\\')));
    if (!(await existsAsync(cacheDir))) {
      await mkdir(cacheDir, { recursive: true });
    }
    await writeFile(
      cachePath,
      JSON.stringify({
        timestamp: Date.now(),
        dateTime: formatDateTime(),
        apps,
      }, null, 2),
      'utf-8',
    );
  } catch (error) {
    console.error('save cache file error:', error);
  }
}

// 获取已安装软件列表（带缓存）
export async function getInstalledApps (
  forceRefresh = false,
): Promise<InstalledApp[]> {
  if (process.platform !== 'win32') {
    return [];
  }

  // 如果不是强制刷新，先尝试从缓存读取
  if (!forceRefresh) {
    const cachedApps = await getAppsFromCache();
    if (cachedApps) {
      return cachedApps;
    }
  }

  // 从注册表获取已安装应用
  const installedApps = await scriptManager.getInstalledAppsFromRegistry();
  console.log(`[getInstalledApps] 从注册表获取到 ${installedApps.length} 个应用`);
  
  // 获取系统应用
  const systemApps = await scriptManager.getSystemApps();
  console.log(`[getInstalledApps] 获取到 ${systemApps.length} 个系统应用`, systemApps.map(a => a.name).slice(0, 10));
  
  // 合并应用列表，系统应用优先（避免重复）
  const appNameMap = new Map<string, InstalledApp>();
  
  // 先添加系统应用
  for (const app of systemApps) {
    appNameMap.set(app.name, app);
  }
  
  // 再添加已安装应用（如果名称不重复）
  for (const app of installedApps) {
    if (!appNameMap.has(app.name)) {
      appNameMap.set(app.name, app);
    }
  }
  
  const apps = Array.from(appNameMap.values());
  console.log(`[getInstalledApps] 合并后共有 ${apps.length} 个应用`);
  
  // 为每个应用提取并保存图标
  const appsWithIcons = await Promise.all(
    apps.map(async (app) => {
      // 如果 icon 已经是本地路径（file://），跳过
      if (app.icon?.startsWith('file://')) {
        return app;
      }
      
      // 对于 URI 类型的路径（如 ms-settings:），特殊处理
      // URI 协议通常格式为 protocol:，且不包含反斜杠或正斜杠（除了协议分隔符）
      const isUri = app.mainFilePath && 
        /^[a-z][a-z0-9+.-]*:/.test(app.mainFilePath) && 
        !app.mainFilePath.includes('\\') && 
        !app.mainFilePath.match(/^[a-z]:/i); // 排除 Windows 盘符路径（如 C:\）
      
      // 如果是 URI 类型，但已经有图标路径（如系统设置），尝试提取图标
      if (isUri) {
        // 系统设置可能有从应用包获取的图标路径
        if (app.name === '系统设置' && app.icon && !app.icon.startsWith('file://') && app.icon.includes('\\')) {
          // 有图标路径，继续提取图标
        } else {
          // 没有图标路径，跳过
          return app;
        }
      }
      
      // 收集所有可能的图标路径
      const allIconPaths: string[] = [];
      
      // 1. 如果有 mainFilePath（系统应用通常有这个），优先使用
      // 但如果是 URI 类型，跳过（因为 URI 不是文件路径）
      if (app.mainFilePath && !app.mainFilePath.startsWith('file://') && !isUri) {
        allIconPaths.push(app.mainFilePath);
      }
      
      // 2. 如果有 DisplayIcon，使用
      if (app.icon && !app.icon.startsWith('file://')) {
        // 对于 URI 类型的应用，如果 icon 是文件路径，使用它
        if (isUri && app.icon.includes('\\')) {
          allIconPaths.push(app.icon);
        } else if (!isUri) {
          if (!allIconPaths.includes(app.icon)) {
            allIconPaths.push(app.icon);
          }
        }
      }
      
      // 对于 URI 类型，也检查 displayIcon
      if (isUri && app.displayIcon && !app.displayIcon.startsWith('file://') && app.displayIcon.includes('\\')) {
        if (!allIconPaths.includes(app.displayIcon)) {
          allIconPaths.push(app.displayIcon);
        }
      }
      
      // 3. 从 uninstallString 中提取
      if (app.uninstallString) {
        const uninstallMatch = app.uninstallString.match(/^["']?([^"'\s]+\.exe["']?)/i);
        if (uninstallMatch) {
          const exePath = uninstallMatch[1].replace(/["']/g, '');
          if (!allIconPaths.includes(exePath)) {
            allIconPaths.push(exePath);
          }
        }
      }
      
      // 3. 从 installLocation 中查找
      if (app.installLocation) {
        // 首先尝试固定的常见 exe 文件名
        const possibleExeNames = [
          'uninstall.exe',
          'setup.exe',
          'install.exe',
          'app.exe',
          'main.exe',
          'launcher.exe',
        ];
        if (app.mainFilePath) {
          possibleExeNames.unshift(basename(app.mainFilePath))
        }

        for (const exeName of possibleExeNames) {
          const possiblePath = join(app.installLocation, exeName);
          if (
            await existsAsync(possiblePath) &&
            !allIconPaths.includes(possiblePath)
          ) {
            allIconPaths.push(possiblePath);
          }
        }
        
        // 如果固定名称没找到，查找目录中的所有 exe 文件
        const hasIconFromOtherSources =
          (app.icon ? 1 : 0) + (app.uninstallString ? 1 : 0);
        if (allIconPaths.length === hasIconFromOtherSources) {
          const exeFiles = await findExeFilesInDirectory(app.installLocation);
          console.log(
            `[${app.name}] find ${exeFiles.length} exe files in directory ${app.installLocation}`,
          );
          
          // 优先选择名称与应用名称相似的 exe 文件
          const appNameLower = app.name.toLowerCase();
          const matchingExe = exeFiles.find(exe => {
            const exeName = exe.toLowerCase();
            const fileName = exeName.split('\\').pop()?.replace('.exe', '') || '';
            return exeName.includes(appNameLower) || 
                   appNameLower.includes(fileName) ||
                   fileName.includes(appNameLower.split(' ')[0]); // 匹配第一个单词
          });
          
          if (matchingExe && !allIconPaths.includes(matchingExe)) {
            allIconPaths.push(matchingExe);
            console.log(`[${app.name}] select matching exe: ${matchingExe}`);
          } else if (exeFiles.length > 0) {
            // 如果没有匹配的，使用第一个找到的 exe 文件
            const firstExe = exeFiles[0];
            if (!allIconPaths.includes(firstExe)) {
              allIconPaths.push(firstExe);
              console.log(`[${app.name}] select first exe: ${firstExe}`);
            }
          }
        }
      }
      
      // 尝试所有路径
      if (allIconPaths.length > 0) {
        console.log(
          `[${app.name}] try ${allIconPaths.length} icon paths:`,
          allIconPaths,
        );
        const localIconPath = await extractAndSaveIcon(
          allIconPaths[0],
          app.name,
          allIconPaths.slice(1),
        );
        if (localIconPath) {
          console.log(`[${app.name}] success extract icon: ${localIconPath}`);
        } else {
          console.warn(`[${app.name}] all paths failed, cannot extract icon`);
        }
        return {
          ...app,
          icon: localIconPath || undefined,
        };
      } else {
        console.warn(`[${app.name}] no available icon paths`);
      }
      
      return app;
    }),
  );
  
  // 保存到缓存
  if (appsWithIcons.length > 0) {
    await saveAppsToCache(appsWithIcons);
  }

  return appsWithIcons;
}

// 搜索已安装软件
export function searchInstalledApps (
  apps: InstalledApp[],
  keyword: string,
): InstalledApp[] {
  if (!keyword) {
    return [];
  }

  const lowerKeyword = keyword.toLowerCase();
  return apps.filter(app => {
    const name = app.name?.toLowerCase() || '';
    const publisher = app.publisher?.toLowerCase() || '';
    return name.includes(lowerKeyword) || publisher.includes(lowerKeyword);
  });
}

